package rensoft.android;

import static rensoft.android.lang.AndroidLang.event;
import static rensoft.java.lang.Lang.is;
import static rensoft.java.lang.Lang.no;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.Display;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.DatePicker;
import android.widget.EditText;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.ScrollView;
import android.widget.TextView;
import android.widget.ToggleButton;
import android.widget.ViewAnimator;
import rensoft.android.lang.IRequest;
import rensoft.android.view.RequestPresenter;
import rensoft.android.view.grid.GridDataPresenter;
import rensoft.android.view.grid.IGridRequest;
import rensoft.java.collections.Map;
import rensoft.java.event.Event;
import rensoft.java.lang.Callback;

public abstract class ActivityPresenter extends ContextPresenter implements HasActivity {

  protected final Activity activity;
  private final Event<Void> eventPause = event();
  private final Event<Bundle> eventCreate = event();
  private final Event<Void> eventStart = event();
  private final Event<Void> eventStop = event();
  private final Event<Bundle> eventSaveInstance = event();
  private final Event<Map<String, Object>> eventRetainNonConfigurationInstance = event();
  private final Event<Map<String, Object>> eventRestoreNonConfigurationInstance = event();
  private final Event<Void> eventDestroy = event();
  private final Event<Void> eventResume = event();
  private final Event<ActivityResult> eventActivityResult = event();
  private boolean paused;

  ActivityPresenter(Activity activity) {
    super(activity);
    this.activity = activity;
  }

  public Activity activity() {
    return activity;
  }

  @Override
  public Event<ActivityResult> getOnActivityResult() {
    return eventActivityResult;
  }

  public Event<Bundle> getOnCreate() {
    return eventCreate;
  }

  public Event<Void> getOnDestroy() {
    return eventDestroy;
  }

  public Event<Void> getOnPause() {
    return eventPause;
  }

  public Event<Map<String, Object>> getOnRestoreNonConfigurationInstance() {
    return eventRestoreNonConfigurationInstance;
  }

  public Event<Void> getOnResume() {
    return eventResume;
  }

  public Event<Map<String, Object>> getOnRetainNonConfigurationInstance() {
    return eventRetainNonConfigurationInstance;
  }

  public Event<Bundle> getOnSaveInstance() {
    return eventSaveInstance;
  }

  public Event<Void> getOnStart() {
    return eventStart;
  }

  public Event<Void> getOnStop() {
    return eventStop;
  }

  public View inflateLayout(int layout_id) {
    return activity.getLayoutInflater().inflate(layout_id, null);
  }

  public boolean isPaused() {
    return paused;
  }

  public void onActivityResult(int requestCode, int resultCode, Intent data) {
    fire(eventActivityResult, new ActivityResult(requestCode, resultCode, data));
  }

  public void onCreate(Bundle state) {
    onCreate();
    if (no(state))
      onCreateFirstTime();
    else onCreateRestore(state);
    fire(eventCreate, state);
  }

  public void onDestroy() {
    fire(eventDestroy);
  }

  public void onPause() {
    paused = true;
    fire(eventPause);
  }

  public void onResume() {
    paused = false;
    fire(eventResume);
  }

  public void onSaveInstanceState(Bundle state) {
    fire(eventSaveInstance, state);
  }

  public void onStart() {
    fire(eventStart);
  }

  public void onStop() {
    free();
    fire(eventStop);
  }

  protected Button getButton(int id) {
    return (Button) activity.findViewById(id);
  }

  protected DatePicker getDatePicker(int id) {
    return (DatePicker) activity.findViewById(id);
  }

  protected Display getDisplay() {
    return activity.getWindowManager().getDefaultDisplay();
  }

  protected EditText getEditText(int id) {
    return (EditText) activity.findViewById(id);
  }

  protected FrameLayout getFrameLayout(int id) {
    return (FrameLayout) getView(id);
  }

  protected ImageView getImageView(int id) {
    return (ImageView) activity.findViewById(id);
  }

  protected LinearLayout getLinearLayout(int id) {
    return (LinearLayout) activity.findViewById(id);
  }

  protected ListView getListView(int id) {
    return (ListView) activity.findViewById(id);
  }

  protected RadioButton getRadioButton(int id) {
    return (RadioButton) activity.findViewById(id);
  }

  protected RadioGroup getRadioGroup(int id) {
    return (RadioGroup) activity.findViewById(id);
  }

  protected ScrollView getScrollView(int id) {
    return (ScrollView) activity.findViewById(id);
  }

  protected TextView getTextView(int id) {
    return (TextView) activity.findViewById(id);
  }

  protected ToggleButton getToggleButton(int id) {
    return (ToggleButton) activity.findViewById(id);
  }

  protected View getView(int id) {
    return activity.findViewById(id);
  }

  protected ViewAnimator getViewAnimator(int id) {
    return (ViewAnimator) getView(id);
  }

  protected void hide(int... viewIds) {
    for (int id : viewIds)
      hide(getView(id));
  }

  protected void hide(View view) {
    view.setVisibility(View.GONE);
  }

  protected boolean isMainActivityRun() {
    return Intent.ACTION_MAIN.equals(activity.getIntent().getAction());
  }

  protected boolean isVisible(int id) {
    return isVisible(getView(id));
  }

  protected boolean isVisible(View view) {
    return view.getVisibility() == View.VISIBLE;
  }

  protected void onCreate() {}

  protected void onCreateFirstTime() {}

  @SuppressWarnings("unchecked")
  protected void onCreateRestore(Bundle state) {
    Object nonConfigurationInstance = activity.getLastNonConfigurationInstance();
    if (is(nonConfigurationInstance))
      onRestoreNonConfigurationInstance((Map<String, Object>) nonConfigurationInstance);
  }

  protected void onRestoreNonConfigurationInstance(Map<String, Object> instance) {
    fire(eventRestoreNonConfigurationInstance, instance);
  }

  protected void onRetainNonConfigurationInstance(Map<String, Object> instance) {
    fire(eventRetainNonConfigurationInstance, instance);
  }

  protected void registerGridDataFailed(GridDataPresenter<IGridRequest> dataPresenter) {
    dataPresenter.setFailedListener(new Callback<IGridRequest>() {
      public void onCall(IGridRequest value) {
        MainActivityPresenter.getInstance().onRequestFailed(value);
      }
    });
  }

  protected <T extends IRequest> void registerRequestFailed(RequestPresenter<T> presenter) {
    presenter.setFailedListener(new Callback<T>() {
      public void onCall(T value) {
        MainActivityPresenter.getInstance().onRequestFailed(value);
      }
    });
  }

  protected void setContentView(int layoutResId) {
    activity.setContentView(layoutResId);
  }

  protected void setOnClickListener(OnClickListener onClickListener, int... ids) {
    for (int id : ids)
      getView(id).setOnClickListener(onClickListener);
  }

  protected void setViewVisible(int viewId, boolean visible) {
    if (visible)
      show(viewId);
    else hide(viewId);
  }

  protected void show(int... viewIds) {
    for (int id : viewIds)
      show(getView(id));
  }

  protected void show(View view) {
    view.setVisibility(View.VISIBLE);
  }

  protected void startActivity(Class<? extends Activity> activityClass) {
    startActivity(new Intent(activity, activityClass));
  }

  protected void startActivity(Intent intent) {
    activity.startActivity(intent);
  }

  protected void startActivityForResult(Intent intent, int requestCode) {
    activity.startActivityForResult(intent, requestCode);
  }

  protected void switchActivity(Class<? extends Activity> activityClass) {
    switchActivity(new Intent(activity, activityClass));
  }

  protected void switchActivity(Intent intent) {
    startActivity(intent);
    activity.finish();
  }

  public class ActivityResult {
    public final int requestCode;
    public final int resultCode;
    public final Intent data;

    public ActivityResult(int requestCode, int resultCode, Intent data) {
      this.requestCode = requestCode;
      this.resultCode = resultCode;
      this.data = data;
    }
  }

}
